﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Mvc.Html;
using System.Reflection;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Data.Linq;

namespace yao.Mvc
{
    public static partial class HtmlExtensions
    {
        private static RouteValueDictionary AnonymousObjectToDictionary(object properties)
        {
            if (properties is RouteValueDictionary)
            {
                return properties as RouteValueDictionary;
            }
            if (properties is IEnumerable<KeyValuePair<string, object>>)
            {
                var routeValues = new RouteValueDictionary();
                foreach (KeyValuePair<string, object> keyValuePair in (IEnumerable<KeyValuePair<string, object>>)properties)
                {
                    routeValues.Add(keyValuePair.Key, keyValuePair.Value);
                }
                return routeValues;
            }
            RouteValueDictionary dictionary = new RouteValueDictionary();
            if (properties != null)
            {
                foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(properties))
                {
                    dictionary.Add(descriptor.Name, descriptor.GetValue(properties));
                }
            }
            return dictionary;
        }
        private static void GenerateAcronym(this HtmlHelper htmlHelper, StringBuilder sb, string name, object verification)
        {
            sb.AppendFormat("<acronym for=\"{0}\">", name);
            if (verification != null)
            {
                //htmlHelper.ViewData["Test"] = 123;
                IDictionary<string, object> dic = AnonymousObjectToDictionary(verification);
                foreach (var d in dic)
                {
                    if (d.Value.GetType().IsValueType || d.Value is string)
                    {
                        sb.AppendFormat("<{0}>{1}</{0}>", d.Key, d.Value);
                    }
                    else
                    {
                        IDictionary<string, object> dic1 = AnonymousObjectToDictionary(d.Value);
                        sb.AppendFormat("<{0}", d.Key);
                        foreach (var o in dic1)
                        {
                            sb.AppendFormat("  {0}=\"{1}\"", o.Key, o.Value);
                        }
                        sb.AppendFormat("></{0}>", d.Key);
                    }
                }
            }
            sb.Append("</acronym>");
        }
        
        private static void GenerateMessage(this HtmlHelper htmlHelper, StringBuilder sb, string name, object message)
        {
            if (message == null)
            {
                sb.AppendFormat("<span for=\"{0}\"></span>", name);
            }
            else
            {
                IDictionary<string, object> dic = AnonymousObjectToDictionary(message);
                if (htmlHelper.ViewData.ModelState[name] != null &&
                htmlHelper.ViewData.ModelState[name].Errors.Count > 0)
                {
                    StringBuilder sberror = new StringBuilder();
                    int i = 0;
                    foreach (var error in htmlHelper.ViewData.ModelState[name].Errors)
                    {
                        if (i > 0)
                        {
                            sberror.Append(",");
                        }
                        sberror.Append(error.ErrorMessage);
                    }
                    sb.AppendFormat("<span for=\"{0}\" class=\"error\">{1}</span>", name, sberror.ToString());

                }
                else
                {
                    if (dic["title"] != null)
                    {
                        sb.AppendFormat("<span for=\"{0}\" class=\"nomal\">{1}</span>", name, dic["helper"]);
                    }
                }
                sb.AppendFormat("<helper for=\"{0}\" ", name);
                foreach (var d in dic)
                {
                    sb.AppendFormat(" {0}=\"{1}\"", d.Key, d.Value);
                }
                sb.Append("></helper>");
            }
        }

        private static void GenerateFormItem(this StringBuilder sb, string label, IDictionary<string, object> validates, HtmlString inputHtmlString, bool isBlock = false)
        {
            if (isBlock)
            {
                sb.Append("<div class=\"form-item\">\r\n");
            }
            else
            {
                sb.Append("<div class=\"form-item inline-block\">\r\n");
            }
            sb.AppendFormat("  <div class=\"label\">{0}", label);
            if (validates != null && validates.Count > 0 && validates.ContainsKey("req"))
            {
                sb.Append("<div class=\"c2 inline-block req\">*</div>");
            }
            sb.Append("</div>\r\n");
            sb.Append("  <div class=\"content\">\r\n");
            sb.Append(inputHtmlString);
            sb.Append("  </div>\r\n");
            sb.Append("</div>\r\n");
        }


        #region LTextEdit
        public static HtmlString LTextEdit(this HtmlHelper htmlHelper, string name,  string value,  object verification, object message)
        {
            return htmlHelper.LTextEdit(name, value, new { Class = "inp-text" }, verification, message);
        }
        public static HtmlString LTextEdit(this HtmlHelper htmlHelper, string name,   object verification, object message)
        {
            return htmlHelper.LTextEdit(name, "", new { Class = "inp-text" }, verification, message);
        }

        public static HtmlString LTextEdit(this HtmlHelper htmlHelper, string name,  object param, object verification, object message)
        {
            return htmlHelper.LTextEdit(name,"", param, verification, message);
        }
      
        public static HtmlString LTextEdit(this HtmlHelper htmlHelper, string name,  string value, object param, object verification, object message)
        {
            return htmlHelper.LTextEdit(name, value, "text", param, verification, message);
        }
        
        public static HtmlString LPassword1(this HtmlHelper htmlHelper, string name,  object param, object verification, object message)
        {
            return htmlHelper.LTextEdit(name, "", "password", param, verification, message);
        }
        public static HtmlString LPassword1(this HtmlHelper htmlHelper, string name,  object verification, object message)
        {
            return htmlHelper.LTextEdit(name, "",  "password", new { Class = "inp-text" }, verification, message);
        }
        
        public static HtmlString LPassword1(this HtmlHelper htmlHelper, string name,  string value, object param, object verification, object message)
        {
            return htmlHelper.LTextEdit(name,value, "password", param, verification, message);
        }

        /// <summary>
        /// text 文本输入框扩展
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="name">name</param>
        /// <param name="value">value</param>
        /// <param name="type"></param>
        /// <param name="param">属性</param>
        /// <param name="verification">验证设置</param>
        /// <param name="message">信息设置</param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static HtmlString LTextEdit(this HtmlHelper htmlHelper, string name, string value, string type, object param, object verification, object message)
        {
           return htmlHelper.LTextEdit(name, value, null, type, param, verification, message);
        }

        public static HtmlString LTextEdit(this HtmlHelper htmlHelper, string name,string value,string forName, string type, object param, object verification, object message)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException("name");
            }
            
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("<input type=\"{1}\" name=\"{0}\"  id=\"{0}\" autocomplete=\"off\"", name, type);
            if (!string.IsNullOrEmpty(value))
            {
                sb.AppendFormat(" value =\"{0}\"", value);
            }

            IDictionary<string, object> inputAttrDic = new RouteValueDictionary();
            if (param != null)
            {
                inputAttrDic = AnonymousObjectToDictionary(param);
            }
            foreach (var d in inputAttrDic)
            {
                sb.AppendFormat(" {0}=\"{1}\"", d.Key, d.Value);
            }
            sb.Append("/>");
            //if (inputAttrDic.ContainsKey("class") && inputAttrDic["class"].ToString().Contains("commonbox"))
            //{
            //    sb.Append("<a href=\"javascript: void(0)\" class=\"l-btn fa absolute fa-angle-down block c5 btn-hg6\" mark=\"Commonbox\"></a>");
            //}
            if (inputAttrDic.ContainsKey("class") && inputAttrDic["class"].ToString().Contains("mapaddress"))
            {
                sb.Append("<a href=\"javascript: void(0)\" class=\"l-btn fa absolute fa-map-marker block c5 btn-hg6\" mark=\"MapAddree\"></a>");
            }

            if (string.IsNullOrEmpty(forName))
            {
                forName = name;
            }
            else {
                string data = string.Empty;
                if (inputAttrDic["data"]!=null) {
                    data = inputAttrDic["data"].ToString();
                    int i;
                    if (int.TryParse(data, out i))
                    {
                        if (i == 0) {
                            data = string.Empty;
                        }
                    }
                }
                sb.AppendFormat("<input type=\"hidden\" name=\"{0}\" id=\"{0}\"  value=\"{1}\"/>",forName,data);
            }


            #region message
            htmlHelper.GenerateMessage(sb, forName, message);
            #endregion

            #region acronym
            htmlHelper.GenerateAcronym(sb, forName, verification);
            #endregion

            return new HtmlString(sb.ToString());
        }     

        #endregion
        #region LTextEditFor
        public static HtmlString LTextEditFor(this HtmlHelper htmlHelper, string name, string displayName, string value,  object verification, object message, bool isblock = true)
        {
            return htmlHelper.LTextEditFor(name, displayName, value, new { Class = "inp-text" }, verification, message,isblock);
        }
        
        public static HtmlString LTextEditFor(this HtmlHelper htmlHelper, string name, string displayName,  object verification, object message, bool isblock = true)
        {
            return htmlHelper.LTextEditFor(name, displayName, "", new { Class = "inp-text" }, verification, message,isblock);
        }

        public static HtmlString LTextEditFor(this HtmlHelper htmlHelper, string name, string displayName,  object param, object verification, object message, bool isblock = true)
        {
            return htmlHelper.LTextEditFor(name, displayName, "", param, verification, message,isblock);
        }

        public static HtmlString LTextEditFor(this HtmlHelper htmlHelper, string name, string displayName, string value,  object param, object verification, object message, bool isblock = true)
        {
            return htmlHelper.LTextEditFor(name, displayName, value, "text", param, verification, message,isblock);
        }

        public static HtmlString LPasswordFor(this HtmlHelper htmlHelper, string name, string displayName, object param, object verification, object message, bool isblock = true)
        {
            return htmlHelper.LTextEditFor(name, displayName, "", "password", param, verification, message,isblock);
        }
        public static HtmlString LPasswordFor(this HtmlHelper htmlHelper, string name, string displayName,  object verification, object message, bool isblock = true)
        {
            return htmlHelper.LTextEditFor(name, displayName, "", "password", new { Class = "inp-text" }, verification, message,isblock);
        }
        public static HtmlString LPasswordFor(this HtmlHelper htmlHelper, string name, string displayName, string value,  object param, object verification, object message, bool isblock = true)
        {
            return htmlHelper.LTextEditFor(name, displayName, value, "password", param, verification, message,isblock);
        }

        public static HtmlString LTextEditFor(this HtmlHelper htmlHelper, string name, string displayName, string value,string type, object param, object verification, object message,bool isblock=true)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("<div class=\"form-item {2}\"><div class=\"label c5\" for=\"{0}\">{1}</div>", name, displayName, isblock ? "" : "inline-block");
            sb.Append("\r\n");
            if (verification != null)
            {
                IDictionary<string, object> dic = AnonymousObjectToDictionary(verification);
                if (dic["req"] != null)
                {
                    sb.Append("<div class=\"req\">*</div>");
                    sb.Append("\r\n");
                }
            }
            sb.AppendFormat("<div class=\"content\" for=\"{0}\">", name);
            sb.Append(htmlHelper.LTextEdit(name, value, type, param, verification, message));
            sb.Append("</div></div>");
            return new HtmlString(sb.ToString());
        }
        public static HtmlString LTextEditFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string displayName, string type, object param, object verification, object message, bool isblock = true)
        {
            ModelMetadata modelMetadata = ModelMetadata.FromLambdaExpression<TModel, TProperty>(expression, htmlHelper.ViewData);
            string name = modelMetadata.PropertyName;
            Func<TModel, TProperty> f = expression.Compile();
            string value = f((TModel)modelMetadata.Container) + "";
            return htmlHelper.LTextEditFor(name,displayName, value,type,param, verification, message,isblock);
        }
        public static HtmlString LTextEditFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string displayName, object param, object verification, object message, bool isblock = true) {
            return htmlHelper.LTextEditFor(expression, displayName, "text", param, verification, message, isblock);
        }
        public static HtmlString LTextEditFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string displayName, object verification, object message, bool isblock = true)
        {
            return htmlHelper.LTextEditFor(expression, displayName, "text", null, verification, message, isblock);
        }
        public static HtmlString LTextEditFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string displayName, bool isblock = true)
        {
            return htmlHelper.LTextEditFor(expression, displayName, "text", null, null, null, isblock);
        }


        public static HtmlString LPasswordFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string displayName, object param, object verification, object message, bool isblock = true)
        {
            ModelMetadata modelMetadata = ModelMetadata.FromLambdaExpression<TModel, TProperty>(expression, htmlHelper.ViewData);
            string name = modelMetadata.PropertyName;
            Func<TModel, TProperty> f = expression.Compile();
            string value = f((TModel)modelMetadata.Container) + "";
            return htmlHelper.LTextEditFor(name, displayName, value, "password", param, verification, message, isblock);
        }
        public static HtmlString LPasswordFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string displayName, object verification, object message, bool isblock = true)
        {
            return htmlHelper.LPasswordFor(expression, displayName, null, verification, message, isblock);
        }
        public static HtmlString LPasswordFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string displayName, bool isblock = true)
        {
            return htmlHelper.LPasswordFor(expression, displayName, null, null, null, isblock);
        }

        #endregion

        #region Area 
        public static HtmlString LTextEditAreaFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object verification, object message)
        {
            ModelMetadata modelMetadata = ModelMetadata.FromLambdaExpression<TModel,TProperty>(expression, htmlHelper.ViewData);
            
            string name = modelMetadata.PropertyName;
            Func<TModel, TProperty> f = expression.Compile();
            string value = f((TModel)modelMetadata.Container) + "";
            return htmlHelper.LTextEditAreaFor(name, value,verification, message);
        }
        public static HtmlString LTextEditAreaFor(this HtmlHelper htmlHelper, string name, string value, object verification, object message)
        {
            return htmlHelper.LTextEditAreaFor(name, value, "", "", "", verification, message);
        }

        public static HtmlString LTextEditAreaFor(this HtmlHelper htmlHelper,string name, string value,string provinceClass,string cityClass,string areaClass, object verification, object message)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("<div class=\"form-item\"><div class=\"label c5\" for=\"{0}\">{1}</div>", name, "地区");
            sb.Append("\r\n");
            if (verification != null)
            {
                IDictionary<string, object> dic = AnonymousObjectToDictionary(verification);
                if (dic["req"] != null)
                {
                    sb.Append("<div class=\"req\">*</div>");
                    sb.Append("\r\n");
                }
            }
            sb.AppendFormat("<div class=\"content relative\" for=\"{0}\">", name);

            sb.Append("<div class=\"relative inline-block l-margin-r4\" >");
            sb.AppendFormat("<input type=\"text\" readonly=\"readonly\" class=\"inp-text bc1 bgc0 commonbox inp-lg4 inp-hg6 {1}\" name=\"{0}\" id=\"{0}\" placeholder=\"选择省份\" fa=\"fa-angle-down\" />", name+"_Province",provinceClass);
            //sb.AppendFormat("<a href=\"javascript:void(0)\" class=\"l-btn fa absolute fa-angle-down block c5 btn-hg6 {0}\" mark=\"Commonbox\"></a>",provinceClass);
            sb.Append("</div>");

            sb.Append("<div class=\"relative inline-block l-margin-r4\" >");
            sb.AppendFormat("<input type=\"text\" readonly=\"readonly\" class=\"inp-text bc1 bgc0 commonbox inp-lg4 inp-hg6 {1}\" name=\"{0}\" id=\"{0}\" placeholder=\"选择城市\" fa=\"fa-angle-down\" />", name + "_City", cityClass);
            //sb.AppendFormat("<a href=\"javascript:void(0)\" class=\"l-btn fa absolute fa-angle-down block c5 btn-hg6 {0}\" mark=\"Commonbox\"></a>",cityClass);
            sb.Append("</div>");

            sb.Append("<div class=\"relative inline-block\" >");
            sb.AppendFormat("<input type=\"text\" readonly=\"readonly\" class=\"inp-text bc1 bgc0 commonbox inp-lg6 inp-hg6 {1}\" name=\"{0}\" id=\"{0}\" placeholder=\"选择县(区)\" fa=\"fa-angle-down\" />", name + "_Area", areaClass);
            //sb.AppendFormat("<a href=\"javascript:void(0)\" class=\"l-btn fa absolute fa-angle-down block c5 btn-hg6 {0}\" mark=\"Commonbox\"></a>",areaClass);
            sb.Append("</div>");
            if (!string.IsNullOrEmpty(value))
            {
                sb.AppendFormat("<input type=\"hidden\" name=\"{0}\" id=\"{0}\" value=\"{1}\"/>",name, value);
            }
            else
            {
                sb.AppendFormat("<input type=\"hidden\" name=\"{0}\" id=\"{0}\" />", name);
            }
            htmlHelper.GenerateMessage(sb, name, message);
            htmlHelper.GenerateAcronym(sb, name, verification);
            sb.Append("</div></div>");

            return new HtmlString(sb.ToString());
        }

        #endregion

        #region FileUpload

        public static HtmlString LFileUploadFor(this HtmlHelper htmlHelper, string name,string value, string displayName,object uploadAttr, object verification, object message, bool isblock = true)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("<div class=\"form-item {2}\"><div class=\"label c5\" for=\"{0}\">{1}</div>", name, displayName, isblock ? "" : "inline-block");
            sb.Append("\r\n");
            if (verification != null)
            {
                IDictionary<string, object> dic = AnonymousObjectToDictionary(verification);
                if (dic["req"] != null)
                {
                    sb.Append("<div class=\"req\">*</div>");
                    sb.Append("\r\n");
                }
            }
            sb.AppendFormat("<div class=\"content relative\" for=\"{0}\">", name);

            sb.Append(htmlHelper.LFileUpload(name,value, displayName, uploadAttr, verification, message));
            
            sb.Append("</div></div>");

            return new HtmlString(sb.ToString());
        }
        public static HtmlString LFileUpload(this HtmlHelper htmlHelper, string name, string value, string displayName, object uploadAttr, object verification, object message)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("<div class=\"l-upload\" tag=\"FileUpload\" name=\"{0}\"",name);
            if (uploadAttr != null)
            {
                IDictionary<string, object> dic = AnonymousObjectToDictionary(uploadAttr);
                foreach (var d in dic)
                {
                    sb.AppendFormat("  {0}=\"{1}\"", d.Key, d.Value);
                }
            }
            sb.Append("></div>");
            sb.AppendFormat("<input type=\"hidden\" name=\"{0}\" id=\"{0}\" value=\"{1}\"/>",name,value);
            htmlHelper.GenerateMessage(sb, name, message);
            htmlHelper.GenerateAcronym(sb, name, verification);
            return new HtmlString(sb.ToString());
        }
        #endregion

        
        #region LEditor
        public static HtmlString LEditor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
            Expression<Func<TModel, TProperty>> expression,
            Func<Expression<Func<TModel, TProperty>>, IDictionary<string, object>, MvcHtmlString> editor)
        {
            return htmlHelper.LEditor(expression, editor, null);
        }

        public static HtmlString LEditor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
            Expression<Func<TModel, TProperty>> expression,
            Func<Expression<Func<TModel, TProperty>>, IDictionary<string, object>, MvcHtmlString> editor,
            object inputAttr)
        {
            return htmlHelper.LEditor(expression, editor, inputAttr, string.Empty);
        }

        public static HtmlString LEditor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
            Expression<Func<TModel, TProperty>> expression,
            Func<Expression<Func<TModel, TProperty>>, IDictionary<string, object>, MvcHtmlString> editor,
            object inputAttr, string helper)
        {
            return htmlHelper.LEditor(expression, editor, inputAttr, null, helper);
        }
        public static HtmlString LEditor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, Func<Expression<Func<TModel, TProperty>>, IDictionary<string, object>, MvcHtmlString> editor, object inputAttr, object validates, string helper)
        {
            //string s = ExpressionHelper.GetExpressionText(expression);
            //var value = modelMetadata.Model;
            ModelMetadata modelMetadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            string propertyName = modelMetadata.PropertyName;

            #region content
            StringBuilder sb = new StringBuilder();
            #region input
            IDictionary<string, object> inputAttrDic = new RouteValueDictionary();
            if (inputAttr != null)
            {
                inputAttrDic = AnonymousObjectToDictionary(inputAttr);
            }

            string @class = "inp-text bc1 bgc0";
            //如果是CheckBox
            if (editor.Method.Name == "CheckBoxFor")
            {
                @class += "  hidden";
            }
            if (inputAttrDic.ContainsKey("class"))
            {
                if (!inputAttrDic["class"].ToString().Contains("inp-lg")) {
                    @class += " inp-lg7";
                }
                if (!inputAttrDic["class"].ToString().Contains("inp-hg"))
                {
                    @class += " inp-hg6";
                }
                @class += " " + inputAttrDic["class"];
                inputAttrDic["class"] = @class;
            }
            else
            {
                inputAttrDic.Add("class", @class+ " inp-lg7 inp-hg6");
            }
            
            MvcHtmlString inputTag = editor(expression, inputAttrDic);
            sb.Append(inputTag.ToHtmlString());
            //if (inputAttrDic.ContainsKey("class") && inputAttrDic["class"].ToString().Contains("commonbox"))
            //{
            //    sb.Append("<a href=\"javascript: void(0)\" class=\"l-btn fa absolute fa-angle-down block c5 btn-hg6\" mark=\"Commonbox\"></a>");
            //}
            if (inputAttrDic.ContainsKey("class") && inputAttrDic["class"].ToString().Contains("mapaddress"))
            {
                if (inputAttrDic.ContainsKey("disabled"))
                {
                    sb.Append("<a href=\"javascript: void(0)\" class=\"l-btn fa absolute fa-map-marker block c5 btn-hg6 disable\" mark=\"MapAddree\"></a>");
                }
                else
                {
                    sb.Append("<a href=\"javascript: void(0)\" class=\"l-btn fa absolute fa-map-marker block c5 btn-hg6 \" mark=\"MapAddree\"></a>");
                }
            }
            //如果是CheckBox
            if (editor.Method.Name == "CheckBoxFor") {
                sb.AppendFormat("<label class=\"checkboxforinput\" for=\"{0}\"></label>",propertyName);
            }
            #endregion

            #region icon
            TreeTagBuilder iconTag = new TreeTagBuilder("span");
            iconTag.MergeAttribute("for", propertyName);

            if (htmlHelper.ViewData.ModelState[propertyName] != null &&
                htmlHelper.ViewData.ModelState[propertyName].Errors.Count > 0)
            {
                iconTag.AddCssClass("error");
                StringBuilder sberror = new StringBuilder();
                int i = 0;
                foreach (var error in htmlHelper.ViewData.ModelState[propertyName].Errors)
                {
                    if (i > 0)
                    {
                        sberror.Append(",");
                    }
                    sberror.Append(error.ErrorMessage);
                }
                iconTag.SetInnerText(sberror.ToString());
            }
            else
            {
                iconTag.AddCssClass("nomal");
            }

            sb.Append(iconTag.ToHtmlString());
            #endregion

            #region helper
            if (!string.IsNullOrWhiteSpace(helper))
            {
                TreeTagBuilder helperTag = new TreeTagBuilder("helper");
                helperTag.MergeAttribute("for", propertyName);
                helperTag.MergeAttribute("title", helper);
                sb.Append(helperTag.ToHtmlString());
            }
            #endregion

            #region validacation
            TreeTagBuilder validateTag = new TreeTagBuilder("acronym");
            validateTag.MergeAttribute("for", propertyName);
            PropertyInfo propertyInfo = modelMetadata.ContainerType.GetProperty(propertyName);
            
            #region 自定义的前端验证
            IDictionary<string, object> validateDic = new RouteValueDictionary();
            if (validates != null)
            {
                validateDic = AnonymousObjectToDictionary(validates);
                foreach (var d in validateDic)
                {
                    IDictionary<string, object> dic1 = AnonymousObjectToDictionary(d.Value);
                    TreeTagBuilder vTag = new TreeTagBuilder(d.Key);
                    foreach (var o in dic1)
                    {
                        vTag.MergeAttribute(o.Key, o.Value.ToString());
                    }
                    validateTag.AppendElement(vTag);
                }
            }
            #endregion

            #region req
            RequiredAttribute requiredAttribute = propertyInfo.GetCustomAttribute<RequiredAttribute>();
            if (requiredAttribute != null)
            {
                TreeTagBuilder reqTag = new TreeTagBuilder("req");
                reqTag.MergeAttribute("message", requiredAttribute.ErrorMessage);
                reqTag.SetInnerText("1");
                validateTag.AppendElement(reqTag);
            }
            #endregion

            #region maxLen
            MaxLengthAttribute maxLengthAttribute = propertyInfo.GetCustomAttribute<MaxLengthAttribute>();
            if (maxLengthAttribute != null)
            {
                TreeTagBuilder maxlenTag = new TreeTagBuilder("maxlen");
                maxlenTag.MergeAttribute("message", maxLengthAttribute.ErrorMessage);
                maxlenTag.MergeAttribute("maxlen", maxLengthAttribute.Length.ToString());
                validateTag.AppendElement(maxlenTag);
            }
            #endregion

            #region minLen
            MinLengthAttribute minLengthAttribute = propertyInfo.GetCustomAttribute<MinLengthAttribute>();
            if (minLengthAttribute != null)
            {
                TreeTagBuilder minlenTag = new TreeTagBuilder("minlen");
                minlenTag.MergeAttribute("message", minLengthAttribute.ErrorMessage);
                minlenTag.MergeAttribute("minlen", minLengthAttribute.Length.ToString());
                validateTag.AppendElement(minlenTag);
            }
            #endregion

            #region reg
            RegularExpressionAttribute regularExpressionAttribute = propertyInfo.GetCustomAttribute<RegularExpressionAttribute>();
            if (regularExpressionAttribute != null)
            {
                TreeTagBuilder regTag = new TreeTagBuilder("reg");
                regTag.MergeAttribute("message", regularExpressionAttribute.ErrorMessage);
                regTag.MergeAttribute("pattern", regularExpressionAttribute.Pattern);
                validateTag.AppendElement(regTag);
            }
            #endregion

            

            sb.Append(validateTag.ToHtmlString());
            #endregion

            #endregion
            return new MvcHtmlString(sb.ToString());

        }
        #endregion
        #region LEditorFor
        public static HtmlString LEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
            Expression<Func<TModel, TProperty>> expression,
            Func<Expression<Func<TModel, TProperty>>, IDictionary<string, object>, MvcHtmlString> editor, bool isblock = true)
        {
            return htmlHelper.LEditorFor(expression, editor, null,isblock);
        }

        public static HtmlString LEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
            Expression<Func<TModel, TProperty>> expression,
            Func<Expression<Func<TModel, TProperty>>, IDictionary<string, object>, MvcHtmlString> editor,
            object inputAttr, bool isblock = true)
        {
            return htmlHelper.LEditorFor(expression, editor, inputAttr, string.Empty,isblock);
        }

        public static HtmlString LEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
            Expression<Func<TModel, TProperty>> expression,
            Func<Expression<Func<TModel, TProperty>>, IDictionary<string, object>, MvcHtmlString> editor,
            object inputAttr, string helper, bool isblock = true)
        {
           return htmlHelper.LEditorFor(expression, editor, inputAttr, null, helper,isblock);
        }

        public static HtmlString LEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, Func<Expression<Func<TModel, TProperty>>, IDictionary<string, object>, MvcHtmlString> editor, object inputAttr, object validates, string helper, bool isblock = true)
        { 
            //string s = ExpressionHelper.GetExpressionText(expression);
            //var value = modelMetadata.Model;
            ModelMetadata modelMetadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            string displayName = modelMetadata.DisplayName;
            string propertyName = modelMetadata.PropertyName;
            PropertyInfo propertyInfo = modelMetadata.ContainerType.GetProperty(propertyName);
            #region form-item

            TreeTagBuilder fieldTag = new TreeTagBuilder("div");
            fieldTag.AddCssClass("form-item");
            if (!isblock)
            {
                fieldTag.AddCssClass("inline-block");
            }

            #region label
            TreeTagBuilder labelTag = new TreeTagBuilder("div");
            labelTag.AddCssClass("c5");
            labelTag.AddCssClass("label");
            labelTag.MergeAttribute("for", propertyName);
            labelTag.SetInnerText(displayName);

            fieldTag.AppendElement(labelTag);
            fieldTag.AppendElement("\r\n");
            #endregion

            RequiredAttribute requiredAttribute = propertyInfo.GetCustomAttribute<RequiredAttribute>();
            if (requiredAttribute != null)
            {
                TreeTagBuilder reqTag = new TreeTagBuilder("div");
                reqTag.AddCssClass("req");
                reqTag.SetInnerText("*");
                fieldTag.AppendElement(reqTag);
                fieldTag.AppendElement("\r\n");
            }

            #region content
            TreeTagBuilder contentTag = new TreeTagBuilder("div");
            contentTag.AddCssClass("content");
            contentTag.MergeAttribute("for", modelMetadata.PropertyName);
            contentTag.InnerHtml = htmlHelper.LEditor(expression,editor,inputAttr,validates,helper).ToHtmlString();
            #endregion
            fieldTag.AppendElement(contentTag);
            #endregion
            return new MvcHtmlString(fieldTag.ToString());

        }
        #endregion


        #region LButton
        public static HtmlString LButton(this HtmlHelper htmlHelper, string text)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<div class=\"form-item form-btnitem\">");
            sb.AppendFormat(
                "<a href=\"javascript:void(0)\" class=\"l-btn submit btn-lg7 btn-hg8\" type=\"submit\" tag=\"button\">{0}</a>",
                text);
            sb.Append("</div>");
            return new HtmlString(sb.ToString());
        }
        #endregion

        #region LActionLink
        public static HtmlString LActionLink(this HtmlHelper htmlHelper,string linkText, string actionName,string controllerName,object routeValues,object htmlAttributes) {
            StringBuilder sb = new StringBuilder();
            string str = UrlHelper.GenerateUrl(null, actionName, controllerName, null, null, null, AnonymousObjectToDictionary(routeValues), htmlHelper.RouteCollection, htmlHelper.ViewContext.RequestContext, true);
            TagBuilder builder = new TagBuilder("a")
            {
                InnerHtml = !string.IsNullOrEmpty(linkText) ? HttpUtility.HtmlEncode(linkText) : string.Empty
            };
            builder.MergeAttributes<string, object>(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
            builder.MergeAttribute("href", "javascript:void(0)");
            builder.MergeAttribute("ref", str);
            return new HtmlString(builder.ToString(TagRenderMode.Normal));
        }
        public static HtmlString LActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, object routeValues)
        {
            return htmlHelper.LActionLink(linkText, actionName, controllerName, routeValues, null);
        }
        public static HtmlString LActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName)
        {
            return htmlHelper.LActionLink(linkText, actionName, controllerName,null);
        }
        public static HtmlString LActionLink(this HtmlHelper htmlHelper, string linkText, string actionName)
        {
            return htmlHelper.LActionLink(linkText, actionName,"");
        }
        public static HtmlString LActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, object routeValues, object htmlAttributes)
        {
            return htmlHelper.LActionLink(linkText, actionName, "",routeValues,htmlAttributes);
        }
        public static HtmlString LActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, object routeValues)
        {
            return htmlHelper.LActionLink(linkText, actionName, "", routeValues);
        }
        #endregion

        #region LDetailItem
        public static HtmlString LDetailItemFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression,bool isblock = true)
        {
            return htmlHelper.LDetailItemFor(expression, null, isblock);
        }
        public static HtmlString LDetailItemFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string format, bool isblock=true)
        {
            ModelMetadata modelMetadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            string displayName = modelMetadata.DisplayName;
            string propertyName = modelMetadata.PropertyName;
            
            TreeTagBuilder fieldTag = new TreeTagBuilder("div");
            fieldTag.AddCssClass("detail-item");
            if (!isblock)
            {
                fieldTag.AddCssClass("inline-block");
            }

            #region label
            TreeTagBuilder labelTag = new TreeTagBuilder("div");
            labelTag.AddCssClass("c5");
            labelTag.AddCssClass("label");
            labelTag.SetInnerText(displayName);
            fieldTag.AppendElement(labelTag);
            fieldTag.AppendElement("\r\n");
            #endregion

            #region content
            TreeTagBuilder contentTag = new TreeTagBuilder("div");
            contentTag.AddCssClass("content");
            string innerHtml = FormatValueInternal(modelMetadata.Model, format);
            contentTag.InnerHtml = innerHtml;
            fieldTag.AppendElement(contentTag);
            #endregion
            return new MvcHtmlString(fieldTag.ToString());
        }

        static string FormatValueInternal(object value, string format)
        {
            if (value == null)
            {
                return "--";
            }

            if (String.IsNullOrEmpty(format))
            {
                return Convert.ToString(value, CultureInfo.CurrentCulture);
            }
            else
            {
                return String.Format(CultureInfo.CurrentCulture, format, value);
            }
        }

        #endregion

        #region LAjaxPost
        public static HtmlString LAjaxPost(this HtmlHelper htmlHelper,string name,object htmlAttributes)
        {
            TagBuilder tagA = new TagBuilder("a");
            tagA.MergeAttribute("href", "javascript:void(0)");
            tagA.MergeAttribute("ajaxpost", "ajaxpost");
            tagA.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
            tagA.InnerHtml = name;
            return new HtmlString(tagA.ToString(TagRenderMode.Normal));
        }
        #endregion

        #region Pager 分页
        public static HtmlString Pager(this HtmlHelper htmlHelper,string actionName,string controllerName, object routeValues, long totalCount, int pageIndex, int pageSize) {
            PageHelper pageHelper = new PageHelper(htmlHelper, actionName, controllerName, AnonymousObjectToDictionary(routeValues), totalCount, pageIndex, pageSize);
            return new HtmlString(pageHelper.GeneratePager());
        }
        public static HtmlString Pager(this HtmlHelper htmlHelper, string actionName, string controllerName, long totalCount, int pageIndex, int pageSize)
        {
            return htmlHelper.Pager(actionName, controllerName, new RouteValueDictionary(), totalCount, pageIndex, pageSize);
        }
        #endregion


        #region 全局业务逻辑错误
        public static HtmlString LPageError(this HtmlHelper htmlHelper)
        {
            if (htmlHelper.ViewData["BusinessPageError"] == null)
            {
                return null;
            }
            if (((List<string>) htmlHelper.ViewData["BusinessPageError"]).Count <= 0)
            {
                return null;
            }
            return new HtmlString(string.Format("<div class=\"form-item c0\">{0}</div>", ((List<string>)htmlHelper.ViewData["BusinessPageError"])[0]));
        }
        #endregion
    }

    public static partial class HtmlExtensions
    {
        #region Text
        public static HtmlString LTextBox(this HtmlHelper htmlHelper, string name, object value, string format, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            return InputHelper(htmlHelper,
                               InputType.Text,
                               metadata: null,
                               name: name,
                               value: value,
                               useViewData: (value == null),
                               isChecked: false,
                               setId: true,
                               isExplicitValue: true,
                               format: format,
                               htmlAttributes: htmlAttributes,
                               validates: validates,
                               message: message);
        }
        public static HtmlString LTextBox(this HtmlHelper htmlHelper, string name, object value, string format, object htmlAttributes, object validates, object message)
        {
            return LTextBox(htmlHelper,
                name: name,
                value: value,
                format: format,
                htmlAttributes: HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                validates: HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                message: HtmlHelper.AnonymousObjectToHtmlAttributes(message)
                );
        }
        public static HtmlString LTextBox(this HtmlHelper htmlHelper, string name, object value, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            return htmlHelper.LTextBox(name, value, format: null, htmlAttributes: htmlAttributes, validates: validates, message: message);
        }
        public static HtmlString LTextBox(this HtmlHelper htmlHelper, string name, object value, object htmlAttributes, object validates, object message)
        {
            return htmlHelper.LTextBox(name, value,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                 HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }

        public static HtmlString LTextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string format, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            return TextBoxHelper(htmlHelper,
                                metadata,
                                metadata.Model,
                                ExpressionHelper.GetExpressionText(expression),
                                format,
                                htmlAttributes,
                                validates,
                                message);
        }
        public static HtmlString LTextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string format, object htmlAttributes, object validates, object message)
        {
            return LTextBoxFor(htmlHelper,
                expression,
                format,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message)
                );
        }
        public static HtmlString LTextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes, object validates, object message)
        {
            return htmlHelper.LTextBoxFor(expression, format: null, htmlAttributes: htmlAttributes, validates: validates, message: message);
        }
        public static HtmlString LTextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
        {
            return htmlHelper.LTextBoxFor(expression, htmlAttributes: htmlAttributes, validates: null, message: null);
        }
        public static HtmlString LTextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
        {
            return htmlHelper.LTextBoxFor(expression, htmlAttributes: null);
        }


        public static HtmlString LTextEditor(this HtmlHelper htmlHelper, string label, string name, object value, string format, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(label, validates, LTextBox(htmlHelper, name, value, format, htmlAttributes, validates, message));
            return MvcHtmlString.Create(sb.ToString());
        }
        public static HtmlString LTextEditor(this HtmlHelper htmlHelper, string label, string name, object value, string format, object htmlAttributes, object validates, object message)
        {
            return LTextEditor(htmlHelper,
                label,
                name,
                value,
                format,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message)
                );
        }
        public static HtmlString LTextEditor(this HtmlHelper htmlHelper, string label, string name, object value, object htmlAttributes, object validates, object message)
        {
            return htmlHelper.LTextEditor(label, name, value, format: null, htmlAttributes: htmlAttributes, validates: validates, message: message);
        }
        public static HtmlString LTextEditor(this HtmlHelper htmlHelper, string label, string name, object value, object htmlAttributes)
        {
            return htmlHelper.LTextEditor(label, name, value, htmlAttributes: htmlAttributes, validates: null, message: null);
        }
        public static HtmlString LTextEditor(this HtmlHelper htmlHelper, string label, string name, object value)
        {
            return htmlHelper.LTextEditor(label, name, value, htmlAttributes: null);
        }
        public static HtmlString LTextEditor(this HtmlHelper htmlHelper, string label, string name)
        {
            return htmlHelper.LTextEditor(label, name, value: null);
        }

        public static HtmlString LBlockTextEditor(this HtmlHelper htmlHelper, string label, string name, object value, string format, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(label, validates, LTextBox(htmlHelper, name, value, format, htmlAttributes, validates, message), isBlock: true);
            return MvcHtmlString.Create(sb.ToString());
        }
        public static HtmlString LBlockTextEditor(this HtmlHelper htmlHelper, string label, string name, object value, string format, object htmlAttributes, object validates, object message)
        {
            return LBlockTextEditor(htmlHelper,
                label,
                name,
                value,
                format,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message)
                );
        }
        public static HtmlString LBlockTextEditor(this HtmlHelper htmlHelper, string label, string name, object value, object htmlAttributes, object validates, object message)
        {
            return htmlHelper.LBlockTextEditor(label, name, value, format: null, htmlAttributes: htmlAttributes, validates: validates, message: message);
        }
        public static HtmlString LBlockTextEditor(this HtmlHelper htmlHelper, string label, string name, object value, object htmlAttributes)
        {
            return htmlHelper.LBlockTextEditor(label, name, value, htmlAttributes: htmlAttributes, validates: null, message: null);
        }
        public static HtmlString LBlockTextEditor(this HtmlHelper htmlHelper, string label, string name, object value)
        {
            return htmlHelper.LBlockTextEditor(label, name, value, htmlAttributes: null);
        }
        public static HtmlString LBlockTextEditor(this HtmlHelper htmlHelper, string label, string name)
        {
            return htmlHelper.LBlockTextEditor(label, name, value: null);
        }


        public static HtmlString LTextEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string format, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(metadata.DisplayName, validates, TextBoxHelper(htmlHelper,
                metadata,
                metadata.Model,
                ExpressionHelper.GetExpressionText(expression),
                format,
                htmlAttributes,
                validates,
                message));
            return MvcHtmlString.Create(sb.ToString());
        }
        public static HtmlString LTextEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string format, object htmlAttributes, object validates, object message)
        {
            return LTextEditorFor(htmlHelper,
                expression,
                format,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }
        public static HtmlString LTextEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes, object validates, object message)
        {
            return htmlHelper.LTextEditorFor(expression, format: null, htmlAttributes: htmlAttributes, validates: validates, message: message);
        }
        public static HtmlString LTextEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
        {
            return htmlHelper.LTextEditorFor(expression, htmlAttributes, validates: null, message: null);
        }
        public static HtmlString LTextEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
        {
            return htmlHelper.LTextEditorFor(expression, htmlAttributes: null);
        }

        public static HtmlString LBlockTextEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string format, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(metadata.DisplayName, validates, TextBoxHelper(htmlHelper,
                metadata,
                metadata.Model,
                ExpressionHelper.GetExpressionText(expression),
                format,
                htmlAttributes,
                validates,
                message), isBlock: true);
            return MvcHtmlString.Create(sb.ToString());
        }
        public static HtmlString LBlockTextEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string format, object htmlAttributes, object validates, object message)
        {
            return LBlockTextEditorFor(htmlHelper,
                expression,
                format,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }
        public static HtmlString LBlockTextEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes, object validates, object message)
        {
            return htmlHelper.LBlockTextEditorFor(expression, format: null, htmlAttributes: htmlAttributes, validates: validates, message: message);
        }
        public static HtmlString LBlockTextEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
        {
            return htmlHelper.LBlockTextEditorFor(expression, htmlAttributes, validates: null, message: null);
        }
        public static HtmlString LBlockTextEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
        {
            return htmlHelper.LBlockTextEditorFor(expression, htmlAttributes: null);
        }


        private static MvcHtmlString TextBoxHelper(this HtmlHelper htmlHelper, ModelMetadata metadata, object model, string expression, string format, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            return InputHelper(htmlHelper,
                               InputType.Text,
                               metadata,
                               expression,
                               model,
                               useViewData: false,
                               isChecked: false,
                               setId: true,
                               isExplicitValue: true,
                               format: format,
                               htmlAttributes: htmlAttributes,
                               validates: validates,
                               message: message);
        }
        #endregion

        #region Checkbox
        public static HtmlString LCheckBox(this HtmlHelper htmlHelper, string name, bool isChecked, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            return CheckBoxHelper(htmlHelper, metadata: null, name: name, isChecked: isChecked, htmlAttributes: htmlAttributes, validates: validates, message: message);
        }
        public static HtmlString LCheckBox(this HtmlHelper htmlHelper, string name, bool isChecked, object htmlAttributes, object validates, object message)
        {
            return LCheckBox(htmlHelper, name, isChecked,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message)
                );
        }

        public static MvcHtmlString LCheckBoxFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, bool>> expression, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            if (expression == null)
            {
                throw new ArgumentNullException("expression");
            }

            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            bool? isChecked = null;
            if (metadata.Model != null)
            {
                bool modelChecked;
                if (Boolean.TryParse(metadata.Model.ToString(), out modelChecked))
                {
                    isChecked = modelChecked;
                }
            }

            return CheckBoxHelper(htmlHelper, metadata, ExpressionHelper.GetExpressionText(expression), isChecked, htmlAttributes, validates, message);
        }
        public static MvcHtmlString LCheckBoxFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, bool>> expression, object htmlAttributes, object validates, object message)
        {
            return LCheckBoxFor(htmlHelper, expression,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message)
                );
        }

        public static HtmlString LCheckEditor(this HtmlHelper htmlHelper, string label, string name, bool isChecked, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(label, validates, LCheckBox(htmlHelper, name, isChecked, htmlAttributes, validates, message));
            return MvcHtmlString.Create(sb.ToString());
        }
        public static HtmlString LCheckEditor(this HtmlHelper htmlHelper, string label, string name, bool isChecked, object htmlAttributes, object validates, object message)
        {
            return LCheckEditor(htmlHelper, label, name, isChecked,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }

        public static HtmlString LBlockCheckEditor(this HtmlHelper htmlHelper, string label, string name, bool isChecked, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(label, validates, LCheckBox(htmlHelper, name, isChecked, htmlAttributes, validates, message), isBlock: true);
            return MvcHtmlString.Create(sb.ToString());
        }
        public static HtmlString LBlockCheckEditor(this HtmlHelper htmlHelper, string label, string name, bool isChecked, object htmlAttributes, object validates, object message)
        {
            return LBlockCheckEditor(htmlHelper, label, name, isChecked,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }

        public static MvcHtmlString LCheckEditorFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, bool>> expression, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            if (expression == null)
            {
                throw new ArgumentNullException("expression");
            }

            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            bool? isChecked = null;
            if (metadata.Model != null)
            {
                bool modelChecked;
                if (Boolean.TryParse(metadata.Model.ToString(), out modelChecked))
                {
                    isChecked = modelChecked;
                }
            }
            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(metadata.DisplayName, validates, CheckBoxHelper(htmlHelper, metadata, ExpressionHelper.GetExpressionText(expression), isChecked, htmlAttributes, validates, message));
            return MvcHtmlString.Create(sb.ToString());
        }
        public static MvcHtmlString LCheckEditorFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, bool>> expression, object htmlAttributes, object validates, object message)
        {
            return LCheckEditorFor(htmlHelper, expression,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }

        public static MvcHtmlString LBlockCheckEditorFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, bool>> expression, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            if (expression == null)
            {
                throw new ArgumentNullException("expression");
            }

            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            bool? isChecked = null;
            if (metadata.Model != null)
            {
                bool modelChecked;
                if (Boolean.TryParse(metadata.Model.ToString(), out modelChecked))
                {
                    isChecked = modelChecked;
                }
            }
            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(metadata.DisplayName, validates, CheckBoxHelper(htmlHelper, metadata, ExpressionHelper.GetExpressionText(expression), isChecked, htmlAttributes, validates, message), isBlock: true);
            return MvcHtmlString.Create(sb.ToString());
        }
        public static MvcHtmlString LBlockCheckEditorFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, bool>> expression, object htmlAttributes, object validates, object message)
        {
            return LBlockCheckEditorFor(htmlHelper, expression,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }


        private static MvcHtmlString CheckBoxHelper(HtmlHelper htmlHelper, ModelMetadata metadata, string name, bool? isChecked, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            RouteValueDictionary attributes = ToRouteValueDictionary(htmlAttributes);

            bool explicitValue = isChecked.HasValue;
            if (explicitValue)
            {
                attributes.Remove("checked"); // Explicit value must override dictionary
            }

            return InputHelper(htmlHelper,
                               InputType.CheckBox,
                               metadata,
                               name,
                               value: "true",
                               useViewData: !explicitValue,
                               isChecked: isChecked ?? false,
                               setId: true,
                               isExplicitValue: false,
                               format: null,
                               htmlAttributes: attributes,
                               validates: validates,
                               message: message);
        }
        #endregion

        #region  Hidden
        public static MvcHtmlString LHidden(this HtmlHelper htmlHelper, string name, object value, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            return HiddenHelper(htmlHelper,
                                metadata: null,
                                value: value,
                                useViewData: value == null,
                                expression: name,
                                htmlAttributes: htmlAttributes,
                               validates: validates,
                               message: message);
        }
        public static MvcHtmlString LHidden(this HtmlHelper htmlHelper, string name, object value, object htmlAttributes, object validates, object message)
        {
            return LHidden(htmlHelper, name, value,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }

        public static MvcHtmlString LHiddenFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            return HiddenHelper(htmlHelper,
                                metadata,
                                metadata.Model,
                                false,
                                ExpressionHelper.GetExpressionText(expression),
                                htmlAttributes, validates, message);
        }
        public static MvcHtmlString LHiddenFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes, object validates, object message)
        {
            return LHiddenFor(htmlHelper, expression,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }

        public static MvcHtmlString LHiddenEditor(this HtmlHelper htmlHelper, string label, string name, object value, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(label, validates, LHidden(htmlHelper, name, value, htmlAttributes, validates, message));
            return MvcHtmlString.Create(sb.ToString());
        }
        public static MvcHtmlString LHiddenEditor(this HtmlHelper htmlHelper, string label, string name, object value, object htmlAttributes, object validates, object message)
        {
            return LHiddenEditor(htmlHelper, label, name, value,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }

        public static MvcHtmlString LBlockHiddenEditor(this HtmlHelper htmlHelper, string label, string name, object value, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(label, validates, LHidden(htmlHelper, name, value, htmlAttributes, validates, message), isBlock: true);
            return MvcHtmlString.Create(sb.ToString());
        }
        public static MvcHtmlString LBlockHiddenEditor(this HtmlHelper htmlHelper, string label, string name, object value, object htmlAttributes, object validates, object message)
        {
            return LBlockHiddenEditor(htmlHelper, label, name, value,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }


        public static MvcHtmlString LHiddenEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(metadata.DisplayName, validates, HiddenHelper(htmlHelper,
                                metadata,
                                metadata.Model,
                                false,
                                ExpressionHelper.GetExpressionText(expression),
                                htmlAttributes, validates, message));
            return MvcHtmlString.Create(sb.ToString());
        }
        public static MvcHtmlString LHiddenEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes, object validates, object message)
        {
            return LHiddenEditorFor(htmlHelper, expression,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }

        public static MvcHtmlString LBlockHiddenEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(metadata.DisplayName, validates, HiddenHelper(htmlHelper,
                                metadata,
                                metadata.Model,
                                false,
                                ExpressionHelper.GetExpressionText(expression),
                                htmlAttributes, validates, message), isBlock: true);
            return MvcHtmlString.Create(sb.ToString());
        }
        public static MvcHtmlString LBlockHiddenEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes, object validates, object message)
        {
            return LBlockHiddenEditorFor(htmlHelper, expression,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }


        private static MvcHtmlString HiddenHelper(HtmlHelper htmlHelper, ModelMetadata metadata, object value, bool useViewData, string expression, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            Binary binaryValue = value as Binary;
            if (binaryValue != null)
            {
                value = binaryValue.ToArray();
            }

            byte[] byteArrayValue = value as byte[];
            if (byteArrayValue != null)
            {
                value = Convert.ToBase64String(byteArrayValue);
            }

            return InputHelper(htmlHelper,
                               InputType.Hidden,
                               metadata,
                               expression,
                               value,
                               useViewData,
                               isChecked: false,
                               setId: true,
                               isExplicitValue: true,
                               format: null,
                               htmlAttributes: htmlAttributes,
                               validates: validates,
                               message: message);
        }
        #endregion

        #region Password
        public static MvcHtmlString LPassword(this HtmlHelper htmlHelper, string name, object value, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            return PasswordHelper(htmlHelper, metadata: null, name: name, value: value, htmlAttributes: htmlAttributes, validates: validates, message: message);
        }
        public static MvcHtmlString LPassword(this HtmlHelper htmlHelper, string name, object value, object htmlAttributes, object validates, object message)
        {
            return LPassword(htmlHelper, name, value,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }
        public static MvcHtmlString LPassword(this HtmlHelper htmlHelper, string name, object value, object htmlAttributes)
        {
            return htmlHelper.LPassword(name, value, htmlAttributes, validates: null, message: null);
        }

        public static MvcHtmlString LPasswordFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            if (expression == null)
            {
                throw new ArgumentNullException("expression");
            }

            return PasswordHelper(htmlHelper,
                                  ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData),
                                  ExpressionHelper.GetExpressionText(expression),
                                  value: null,
                                  htmlAttributes: htmlAttributes,
                                  validates: validates,
                                  message: message);
        }
        public static MvcHtmlString LPasswordFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes, object validates, object message)
        {
            return LPasswordFor(htmlHelper, expression,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }
        public static MvcHtmlString LPasswordFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
        {
            return htmlHelper.LPasswordFor(expression, htmlAttributes, validates: null, message: null);
        }

        public static MvcHtmlString LPasswordEditor(this HtmlHelper htmlHelper, string label, string name, object value, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(label, validates, LPassword(htmlHelper, name, value, htmlAttributes, validates, message));
            return MvcHtmlString.Create(sb.ToString());
        }
        public static MvcHtmlString LPasswordEditor(this HtmlHelper htmlHelper, string label, string name, object value, object htmlAttributes, object validates, object message)
        {
            return LPasswordEditor(htmlHelper, label, name, value,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }
        public static MvcHtmlString LPasswordEditor(this HtmlHelper htmlHelper, string label, string name, object value, object htmlAttributes)
        {
            return htmlHelper.LPasswordEditor(label, name, value, htmlAttributes, validates: null, message: null);
        }

        public static MvcHtmlString LBlockPasswordEditor(this HtmlHelper htmlHelper, string label, string name, object value, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(label, validates, LPassword(htmlHelper, name, value, htmlAttributes, validates, message), isBlock: true);
            return MvcHtmlString.Create(sb.ToString());
        }
        public static MvcHtmlString LBlockPasswordEditor(this HtmlHelper htmlHelper, string label, string name, object value, object htmlAttributes, object validates, object message)
        {
            return LPasswordEditor(htmlHelper, label, name, value,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }
        public static MvcHtmlString LBlockPasswordEditor(this HtmlHelper htmlHelper, string label, string name, object value, object htmlAttributes)
        {
            return htmlHelper.LBlockPasswordEditor(label, name, value, htmlAttributes, validates: null, message: null);
        }


        public static MvcHtmlString LPasswordEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            if (expression == null)
            {
                throw new ArgumentNullException("expression");
            }
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);

            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(metadata.DisplayName, validates, PasswordHelper(htmlHelper,
                                  metadata,
                                  ExpressionHelper.GetExpressionText(expression),
                                  value: null,
                                  htmlAttributes: htmlAttributes,
                                  validates: validates,
                                  message: message));
            return MvcHtmlString.Create(sb.ToString());
        }
        public static MvcHtmlString LPasswordEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes, object validates, object message)
        {
            return LPasswordEditorFor(htmlHelper, expression,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }
        public static MvcHtmlString LPasswordEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
        {
            return htmlHelper.LPasswordEditorFor(expression, htmlAttributes, validates: null, message: null);
        }

        public static MvcHtmlString LBlockPasswordEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            if (expression == null)
            {
                throw new ArgumentNullException("expression");
            }
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);

            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(metadata.DisplayName, validates, PasswordHelper(htmlHelper,
                                  metadata,
                                  ExpressionHelper.GetExpressionText(expression),
                                  value: null,
                                  htmlAttributes: htmlAttributes,
                                  validates: validates,
                                  message: message), isBlock: true);
            return MvcHtmlString.Create(sb.ToString());
        }
        public static MvcHtmlString LBlockPasswordEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes, object validates, object message)
        {
            return LBlockPasswordEditorFor(htmlHelper, expression,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }
        public static MvcHtmlString LBlockPasswordEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
        {
            return htmlHelper.LBlockPasswordEditorFor(expression, htmlAttributes, validates: null, message: null);
        }


        private static MvcHtmlString PasswordHelper(HtmlHelper htmlHelper, ModelMetadata metadata, string name, object value, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            return InputHelper(htmlHelper,
                               InputType.Password,
                               metadata,
                               name,
                               value,
                               useViewData: false,
                               isChecked: false,
                               setId: true,
                               isExplicitValue: true,
                               format: null,
                               htmlAttributes: htmlAttributes,
                               validates: validates,
                               message: message);
        }
        #endregion

        #region RadioButton
        public static MvcHtmlString LRadioButton(this HtmlHelper htmlHelper, string name, object value, bool isChecked, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }
            RouteValueDictionary attributes = ToRouteValueDictionary(htmlAttributes);
            attributes.Remove("checked");
            return InputHelper(htmlHelper,
                               InputType.Radio,
                               metadata: null,
                               name: name,
                               value: value,
                               useViewData: false,
                               isChecked: isChecked,
                               setId: true,
                               isExplicitValue: true,
                               format: null,
                               htmlAttributes: attributes,
                               validates: validates,
                               message: message);
        }
        public static MvcHtmlString LRadioButton(this HtmlHelper htmlHelper, string name, object value, bool isChecked, object htmlAttributes, object validates, object message)
        {
            return LRadioButton(htmlHelper, name, value, isChecked,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }

        public static MvcHtmlString LRadioButtonFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object value, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            return RadioButtonHelper(htmlHelper,
                                     metadata,
                                     metadata.Model,
                                     ExpressionHelper.GetExpressionText(expression),
                                     value,
                                     null /* isChecked */,
                                     htmlAttributes,
                                     validates,
                                     message);
        }
        public static MvcHtmlString LRadioButtonFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object value, object htmlAttributes, object validates, object message)
        {
            return LRadioButtonFor(htmlHelper, expression, value,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }

        public static MvcHtmlString LRadioButtonEditor(this HtmlHelper htmlHelper, string label, string name, object value, bool isChecked, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(label, validates, LRadioButton(htmlHelper, name, value, isChecked, htmlAttributes, validates, message));
            return MvcHtmlString.Create(sb.ToString());
        }
        public static MvcHtmlString LRadioButtonEditor(this HtmlHelper htmlHelper, string label, string name, object value, bool isChecked, object htmlAttributes, object validates, object message)
        {
            return LRadioButtonEditor(htmlHelper, label, name, value, isChecked,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }

        public static MvcHtmlString LBlockRadioButtonEditor(this HtmlHelper htmlHelper, string label, string name, object value, bool isChecked, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(label, validates, LRadioButton(htmlHelper, name, value, isChecked, htmlAttributes, validates, message), isBlock: true);
            return MvcHtmlString.Create(sb.ToString());
        }
        public static MvcHtmlString LBlockRadioButtonEditor(this HtmlHelper htmlHelper, string label, string name, object value, bool isChecked, object htmlAttributes, object validates, object message)
        {
            return LBlockRadioButtonEditor(htmlHelper, label, name, value, isChecked,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }


        public static MvcHtmlString LRadioButtonEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object value, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(metadata.DisplayName, validates, RadioButtonHelper(htmlHelper,
                                     metadata,
                                     metadata.Model,
                                     ExpressionHelper.GetExpressionText(expression),
                                     value,
                                     null /* isChecked */,
                                     htmlAttributes,
                                     validates,
                                     message));
            return MvcHtmlString.Create(sb.ToString());
        }
        public static MvcHtmlString LRadioButtonEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object value, object htmlAttributes, object validates, object message)
        {
            return LRadioButtonEditorFor(htmlHelper, expression, value,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }

        public static MvcHtmlString LBlockRadioButtonEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object value, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(metadata.DisplayName, validates, RadioButtonHelper(htmlHelper,
                                     metadata,
                                     metadata.Model,
                                     ExpressionHelper.GetExpressionText(expression),
                                     value,
                                     null /* isChecked */,
                                     htmlAttributes,
                                     validates,
                                     message), isBlock: true);
            return MvcHtmlString.Create(sb.ToString());
        }
        public static MvcHtmlString LBlockRadioButtonEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object value, object htmlAttributes, object validates, object message)
        {
            return LBlockRadioButtonEditorFor(htmlHelper, expression, value,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }


        private static MvcHtmlString RadioButtonHelper(HtmlHelper htmlHelper, ModelMetadata metadata, object model, string name, object value, bool? isChecked, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            RouteValueDictionary attributes = ToRouteValueDictionary(htmlAttributes);

            bool explicitValue = isChecked.HasValue;
            if (explicitValue)
            {
                attributes.Remove("checked"); // Explicit value must override dictionary
            }
            else
            {
                string valueString = Convert.ToString(value, CultureInfo.CurrentCulture);
                isChecked = model != null &&
                            !String.IsNullOrEmpty(name) &&
                            String.Equals(model.ToString(), valueString, StringComparison.OrdinalIgnoreCase);
            }

            return InputHelper(htmlHelper,
                               InputType.Radio,
                               metadata,
                               name,
                               value,
                               useViewData: false,
                               isChecked: isChecked ?? false,
                               setId: true,
                               isExplicitValue: true,
                               format: null,
                               htmlAttributes: attributes,
                               validates: validates,
                               message: message);
        }
        #endregion

        #region TextArea
        private const int TextAreaRows = 2;
        private const int TextAreaColumns = 20;

        private static Dictionary<string, object> implicitRowsAndColumns = new Dictionary<string, object>
        {
            { "rows", TextAreaRows.ToString(CultureInfo.InvariantCulture) },
            { "cols", TextAreaColumns.ToString(CultureInfo.InvariantCulture) },
        };
        public static MvcHtmlString LTextArea(this HtmlHelper htmlHelper, string name, string value, int rows, int columns, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            ModelMetadata metadata = ModelMetadata.FromStringExpression(name, htmlHelper.ViewContext.ViewData);
            if (value != null)
            {
                metadata.Model = value;
            }

            return TextAreaHelper(htmlHelper, metadata, name, GetRowsAndColumnsDictionary(rows, columns), htmlAttributes, validates, message);
        }
        public static MvcHtmlString LTextArea(this HtmlHelper htmlHelper, string name, string value, int rows, int columns, object htmlAttributes, object validates, object message)
        {
            return LTextArea(htmlHelper, name, value, rows, columns,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }

        public static MvcHtmlString LTextAreaFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, int rows, int columns, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            if (expression == null)
            {
                throw new ArgumentNullException("expression");
            }

            return TextAreaHelper(htmlHelper,
                                  ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData),
                                  ExpressionHelper.GetExpressionText(expression),
                                  GetRowsAndColumnsDictionary(rows, columns),
                                  htmlAttributes,
                                  validates,
                                  message);
        }
        public static MvcHtmlString LTextAreaFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, int rows, int columns, object htmlAttributes, object validates, object message)
        {
            return LTextAreaFor(htmlHelper, expression, rows, columns,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }

        public static MvcHtmlString LTextAreaEditor(this HtmlHelper htmlHelper, string label, string name, string value, int rows, int columns, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(label, validates, LTextArea(htmlHelper, name, value, rows, columns, htmlAttributes, validates, message));
            return MvcHtmlString.Create(sb.ToString());
        }
        public static MvcHtmlString LTextAreaEditor(this HtmlHelper htmlHelper, string label, string name, string value, int rows, int columns, object htmlAttributes, object validates, object message)
        {
            return LTextAreaEditor(htmlHelper, name, label, value, rows, columns,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }

        public static MvcHtmlString LBlockTextAreaEditor(this HtmlHelper htmlHelper, string label, string name, string value, int rows, int columns, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(label, validates, LTextArea(htmlHelper, name, value, rows, columns, htmlAttributes, validates, message), isBlock: true);
            return MvcHtmlString.Create(sb.ToString());
        }
        public static MvcHtmlString LBlockTextAreaEditor(this HtmlHelper htmlHelper, string label, string name, string value, int rows, int columns, object htmlAttributes, object validates, object message)
        {
            return LBlockTextAreaEditor(htmlHelper, name, label, value, rows, columns,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }


        public static MvcHtmlString LTextAreaEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, int rows, int columns, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            if (expression == null)
            {
                throw new ArgumentNullException("expression");
            }
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(metadata.DisplayName, validates, TextAreaHelper(htmlHelper,
                                  metadata,
                                  ExpressionHelper.GetExpressionText(expression),
                                  GetRowsAndColumnsDictionary(rows, columns),
                                  htmlAttributes,
                                  validates,
                                  message));
            return MvcHtmlString.Create(sb.ToString());
        }
        public static MvcHtmlString LTextAreaEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, int rows, int columns, object htmlAttributes, object validates, object message)
        {
            return LTextAreaEditorFor(htmlHelper, expression, rows, columns,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }
        public static MvcHtmlString LTextAreaEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes, object validates, object message)
        {
            return htmlHelper.LTextAreaEditorFor(expression, TextAreaRows, TextAreaColumns, htmlAttributes, validates, message);
        }
        public static MvcHtmlString LTextAreaEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
        {
            return htmlHelper.LTextAreaEditorFor(expression, htmlAttributes, validates: null, message: null);
        }
        public static MvcHtmlString LTextAreaEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
        {
            return htmlHelper.LTextAreaEditorFor(expression, htmlAttributes: null);
        }

        public static MvcHtmlString LBlockTextAreaEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, int rows, int columns, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            if (expression == null)
            {
                throw new ArgumentNullException("expression");
            }
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(metadata.DisplayName, validates, TextAreaHelper(htmlHelper,
                                  metadata,
                                  ExpressionHelper.GetExpressionText(expression),
                                  GetRowsAndColumnsDictionary(rows, columns),
                                  htmlAttributes,
                                  validates,
                                  message), isBlock: true);
            return MvcHtmlString.Create(sb.ToString());
        }
        public static MvcHtmlString LBlockTextAreaEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, int rows, int columns, object htmlAttributes, object validates, object message)
        {
            return LBlockTextAreaEditorFor(htmlHelper, expression, rows, columns,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }
        public static MvcHtmlString LBlockTextAreaEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes, object validates, object message)
        {
            return htmlHelper.LBlockTextAreaEditorFor(expression, TextAreaRows, TextAreaColumns, htmlAttributes, validates, message);
        }
        public static MvcHtmlString LBlockTextAreaEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
        {
            return htmlHelper.LBlockTextAreaEditorFor(expression, htmlAttributes, validates: null, message: null);
        }
        public static MvcHtmlString LBlockTextAreaEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
        {
            return htmlHelper.LBlockTextAreaEditorFor(expression, htmlAttributes: null);
        }



        private static MvcHtmlString TextAreaHelper(HtmlHelper htmlHelper, ModelMetadata modelMetadata, string name, IDictionary<string, object> rowsAndColumns, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message, string innerHtmlPrefix = null)
        {
            string fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
            if (String.IsNullOrEmpty(fullName))
            {
                throw new ArgumentException("name");
            }

            TagBuilder tagBuilder = new TagBuilder("textarea");
            tagBuilder.GenerateId(fullName);
            if (htmlAttributes.ContainsKey("class"))
            {
                string classes = "w-input " + htmlAttributes["class"];
                htmlAttributes["class"] = classes;
            }
            else
            {
                htmlAttributes.Add("class", "w-input");
            }
            tagBuilder.MergeAttributes(htmlAttributes, true);
            tagBuilder.MergeAttributes(rowsAndColumns, rowsAndColumns != implicitRowsAndColumns); // Only force explicit rows/cols
            tagBuilder.MergeAttribute("name", fullName, true);

            // If there are any errors for a named field, we add the CSS attribute.
            ModelState modelState;
            if (htmlHelper.ViewData.ModelState.TryGetValue(fullName, out modelState) && modelState.Errors.Count > 0)
            {
                tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
            }

            tagBuilder.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(name, modelMetadata));

            string value;
            if (modelState != null && modelState.Value != null)
            {
                value = modelState.Value.AttemptedValue;
            }
            else if (modelMetadata.Model != null)
            {
                value = modelMetadata.Model.ToString();
            }
            else
            {
                value = String.Empty;
            }

            // The first newline is always trimmed when a TextArea is rendered, so we add an extra one
            // in case the value being rendered is something like "\r\nHello".
            tagBuilder.InnerHtml = (innerHtmlPrefix ?? Environment.NewLine) + HttpUtility.HtmlEncode(value);
            MergeValidates(validates, modelMetadata);
            StringBuilder sb = new StringBuilder();
            sb.Append(tagBuilder.ToString(TagRenderMode.Normal));
            htmlHelper.GenerateMessage(sb, name, message);
            htmlHelper.GenerateAcronym(sb, name, validates);
            return new MvcHtmlString(sb.ToString());
        }
        private static Dictionary<string, object> GetRowsAndColumnsDictionary(int rows, int columns)
        {
            if (rows < 0)
            {
                throw new ArgumentOutOfRangeException("rows");
            }
            if (columns < 0)
            {
                throw new ArgumentOutOfRangeException("columns");
            }

            Dictionary<string, object> result = new Dictionary<string, object>();
            if (rows > 0)
            {
                result.Add("rows", rows.ToString(CultureInfo.InvariantCulture));
            }
            if (columns > 0)
            {
                result.Add("cols", columns.ToString(CultureInfo.InvariantCulture));
            }

            return result;
        }

        #endregion

        #region commnbox
        public static HtmlString Commnbox(this HtmlHelper htmlHelper, string name, object value, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            return CommnboxHelper(htmlHelper, null, name, value, htmlAttributes, validates, message);
        }
        public static HtmlString Commnbox(this HtmlHelper htmlHelper, string name, object value, object htmlAttributes, object validates, object message)
        {
            return Commnbox(htmlHelper, name, value,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }
        public static HtmlString Commnbox(this HtmlHelper htmlHelper, string name, object value, object htmlAttributes)
        {
            return htmlHelper.Commnbox(name, value, htmlAttributes, validates: null, message: null);
        }

        public static HtmlString CommnboxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            return CommnboxHelper(htmlHelper, metadata, ExpressionHelper.GetExpressionText(expression), metadata.Model, htmlAttributes, validates, message);
        }
        public static HtmlString CommnboxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes, object validates, object message)
        {
            return CommnboxFor(htmlHelper, expression,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }
        public static HtmlString CommnboxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
        {
            return htmlHelper.CommnboxFor(expression, htmlAttributes, validates: null, message: null);
        }

        public static HtmlString CommnboxEditor(this HtmlHelper htmlHelper, string label, string name, object value, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(label, validates, Commnbox(htmlHelper, name, value, htmlAttributes, validates, message));
            return MvcHtmlString.Create(sb.ToString());
        }
        public static HtmlString CommnboxEditor(this HtmlHelper htmlHelper, string label, string name, object value, object htmlAttributes, object validates, object message)
        {
            return CommnboxEditor(htmlHelper, label, name, value,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }
        public static HtmlString CommnboxEditor(this HtmlHelper htmlHelper, string label, string name, object value, object htmlAttributes)
        {
            return htmlHelper.CommnboxEditor(label, name, value, htmlAttributes, validates: null, message: null);
        }


        public static HtmlString BlockCommnboxEditor(this HtmlHelper htmlHelper, string label, string name, object value, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(label, validates, Commnbox(htmlHelper, name, value, htmlAttributes, validates, message), isBlock: true);
            return MvcHtmlString.Create(sb.ToString());
        }
        public static HtmlString BlockCommnboxEditor(this HtmlHelper htmlHelper, string label, string name, object value, object htmlAttributes, object validates, object message)
        {
            return BlockCommnboxEditor(htmlHelper, label, name, value,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }
        public static HtmlString BlockCommnboxEditor(this HtmlHelper htmlHelper, string label, string name, object value, object htmlAttributes)
        {
            return htmlHelper.BlockCommnboxEditor(label, name, value, htmlAttributes, validates: null, message: null);
        }


        public static HtmlString CommnboxEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(metadata.DisplayName, validates, CommnboxHelper(htmlHelper, metadata, ExpressionHelper.GetExpressionText(expression), metadata.Model, htmlAttributes, validates, message));
            return MvcHtmlString.Create(sb.ToString());
        }
        public static HtmlString CommnboxEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes, object validates, object message)
        {
            return CommnboxEditorFor(htmlHelper, expression,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }
        public static HtmlString CommnboxEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
        {
            return htmlHelper.CommnboxEditorFor(expression, htmlAttributes, validates: null, message: null);
        }
        public static HtmlString CommnboxEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
        {
            return htmlHelper.CommnboxEditorFor(expression, htmlAttributes: null);
        }

        public static HtmlString BlockCommnboxEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            StringBuilder sb = new StringBuilder();
            sb.GenerateFormItem(metadata.DisplayName, validates, CommnboxHelper(htmlHelper, metadata, ExpressionHelper.GetExpressionText(expression), metadata.Model, htmlAttributes, validates, message), isBlock: true);
            return MvcHtmlString.Create(sb.ToString());
        }
        public static HtmlString BlockCommnboxEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes, object validates, object message)
        {
            return BlockCommnboxEditorFor(htmlHelper, expression,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                HtmlHelper.AnonymousObjectToHtmlAttributes(validates),
                HtmlHelper.AnonymousObjectToHtmlAttributes(message));
        }
        public static HtmlString BlockCommnboxEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
        {
            return htmlHelper.BlockCommnboxEditorFor(expression, htmlAttributes, validates: null, message: null);
        }
        public static HtmlString BlockCommnboxEditorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
        {
            return htmlHelper.BlockCommnboxEditorFor(expression, htmlAttributes: null);
        }


        private static HtmlString CommnboxHelper(this HtmlHelper htmlHelper, ModelMetadata metadata, string name, object value, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            if (htmlAttributes == null)
            {
                htmlAttributes = new Dictionary<string, object>();
            }
            htmlAttributes.Add("name", name + "Box");
            htmlAttributes.Add("id", name + "Box");
            htmlAttributes.Add("class", "commonbox");
            if (!htmlAttributes.ContainsKey("fa"))
            {
                htmlAttributes.Add("fa", "fa-angle-down");
            }
            StringBuilder sb = new StringBuilder();
            if (value.ToString() == "0")
            {
                value = "";
            }
            sb.AppendFormat("<input type=\"hidden\" name=\"{0}\" id=\"{0}\"  value=\"{1}\"/>", name, value);
            sb.Append(InputHelper(htmlHelper,
                               InputType.Text,
                               metadata: metadata,
                               name: name,
                               value: value,
                               useViewData: (value == null),
                               isChecked: false,
                               setId: true,
                               isExplicitValue: false,
                               format: null,
                               htmlAttributes: htmlAttributes,
                               validates: validates,
                               message: message));
            return MvcHtmlString.Create(sb.ToString());
        }
        #endregion

        #region private
        private static MvcHtmlString InputHelper(HtmlHelper htmlHelper, InputType inputType, ModelMetadata metadata, string name, object value, bool useViewData, bool isChecked, bool setId, bool isExplicitValue, string format, IDictionary<string, object> htmlAttributes, IDictionary<string, object> validates, IDictionary<string, object> message)
        {
            string fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
            if (String.IsNullOrEmpty(fullName))
            {
                throw new ArgumentException("name");
            }

            TagBuilder tagBuilder = new TagBuilder("input");
            tagBuilder.MergeAttribute("type", HtmlHelper.GetInputTypeString(inputType));
            if (!htmlAttributes.ContainsKey("name"))
            {
                tagBuilder.MergeAttribute("name", fullName, true);
            }

            if (htmlAttributes.ContainsKey("class"))
            {
                string classes = "w-input " + htmlAttributes["class"];
                htmlAttributes["class"] = classes;
            }
            else
            {
                htmlAttributes.Add("class", "w-input");
            }

            tagBuilder.MergeAttributes(htmlAttributes);

            string valueParameter = htmlHelper.FormatValue(value, format);
            bool usedModelState = false;

            switch (inputType)
            {
                case InputType.CheckBox:
                    bool? modelStateWasChecked = htmlHelper.GetModelStateValue(fullName, typeof(bool)) as bool?;
                    if (modelStateWasChecked.HasValue)
                    {
                        isChecked = modelStateWasChecked.Value;
                        usedModelState = true;
                    }
                    goto case InputType.Radio;
                case InputType.Radio:
                    if (!usedModelState)
                    {
                        string modelStateValue = htmlHelper.GetModelStateValue(fullName, typeof(string)) as string;
                        if (modelStateValue != null)
                        {
                            isChecked = String.Equals(modelStateValue, valueParameter, StringComparison.Ordinal);
                            usedModelState = true;
                        }
                    }
                    if (!usedModelState && useViewData)
                    {
                        isChecked = htmlHelper.EvalBoolean(fullName);
                    }
                    if (isChecked)
                    {
                        tagBuilder.MergeAttribute("checked", "checked");
                    }
                    tagBuilder.MergeAttribute("value", valueParameter, isExplicitValue);
                    break;
                case InputType.Password:
                    if (value != null)
                    {
                        tagBuilder.MergeAttribute("value", valueParameter, isExplicitValue);
                    }
                    break;
                default:
                    string attemptedValue = (string)htmlHelper.GetModelStateValue(fullName, typeof(string));
                    tagBuilder.MergeAttribute("value", attemptedValue ?? ((useViewData) ? htmlHelper.EvalString(fullName, format) : valueParameter), isExplicitValue);
                    break;
            }

            if (setId)
            {
                tagBuilder.GenerateId(fullName);
            }

            // If there are any errors for a named field, we add the css attribute.
            ModelState modelState;
            if (htmlHelper.ViewData.ModelState.TryGetValue(fullName, out modelState))
            {
                if (modelState.Errors.Count > 0)
                {
                    tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
                }
            }

            tagBuilder.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(name, metadata));

            if (inputType == InputType.CheckBox)
            {
                // Render an additional <input type="hidden".../> for checkboxes. This
                // addresses scenarios where unchecked checkboxes are not sent in the request.
                // Sending a hidden input makes it possible to know that the checkbox was present
                // on the page when the request was submitted.
                StringBuilder inputItemBuilder = new StringBuilder();
                inputItemBuilder.Append(tagBuilder.ToString(TagRenderMode.SelfClosing));

                TagBuilder hiddenInput = new TagBuilder("input");
                hiddenInput.MergeAttribute("type", HtmlHelper.GetInputTypeString(InputType.Hidden));
                hiddenInput.MergeAttribute("name", fullName);
                hiddenInput.MergeAttribute("value", "false");
                inputItemBuilder.Append(hiddenInput.ToString(TagRenderMode.SelfClosing));
                return MvcHtmlString.Create(inputItemBuilder.ToString());
            }
            MergeValidates(validates, metadata);
            StringBuilder sb = new StringBuilder();
            sb.Append(tagBuilder.ToString(TagRenderMode.SelfClosing));
            htmlHelper.GenerateMessage(sb, name, message);
            htmlHelper.GenerateAcronym(sb, name, validates);
            return new MvcHtmlString(sb.ToString());
        }
        private static object GetModelStateValue(this HtmlHelper htmlHelper, string key, Type destinationType)
        {
            ModelState modelState;
            if (htmlHelper.ViewData.ModelState.TryGetValue(key, out modelState))
            {
                if (modelState.Value != null)
                {
                    return modelState.Value.ConvertTo(destinationType, null /* culture */);
                }
            }
            return null;
        }
        private static bool EvalBoolean(this HtmlHelper htmlHelper, string key)
        {
            return Convert.ToBoolean(htmlHelper.ViewData.Eval(key), CultureInfo.InvariantCulture);
        }
        private static string EvalString(this HtmlHelper htmlHelper, string key, string format)
        {
            return Convert.ToString(htmlHelper.ViewData.Eval(key, format), CultureInfo.CurrentCulture);
        }
        private static MvcHtmlString ToMvcHtmlString(this TagBuilder tagBuilder, TagRenderMode renderMode)
        {
            return new MvcHtmlString(tagBuilder.ToString(renderMode));
        }
        private static RouteValueDictionary ToRouteValueDictionary(IDictionary<string, object> dictionary)
        {
            return dictionary == null ? new RouteValueDictionary() : new RouteValueDictionary(dictionary);
        }
        private static IDictionary<string, object> MergeValidates(IDictionary<string, object> Validates, ModelMetadata metadata)
        {
            if (metadata == null)
            {
                return Validates;
            }
            string propertyName = metadata.PropertyName;
            PropertyInfo propertyInfo = metadata.ContainerType.GetProperty(propertyName);

            #region req
            RequiredAttribute requiredAttribute = propertyInfo.GetCustomAttribute<RequiredAttribute>();
            if (requiredAttribute != null && !Validates.ContainsKey("req"))
            {
                Validates.Add("req", new { message = requiredAttribute.ErrorMessage });
            }
            #endregion

            #region maxLen
            MaxLengthAttribute maxLengthAttribute = propertyInfo.GetCustomAttribute<MaxLengthAttribute>();
            if (maxLengthAttribute != null && !Validates.ContainsKey("maxlen"))
            {
                Validates.Add("maxlen", new { message = maxLengthAttribute.ErrorMessage, maxlen = maxLengthAttribute.Length.ToString() });
            }
            #endregion

            #region minLen
            MinLengthAttribute minLengthAttribute = propertyInfo.GetCustomAttribute<MinLengthAttribute>();
            if (minLengthAttribute != null && !Validates.ContainsKey("maxlen"))
            {
                Validates.Add("maxlen", new { message = minLengthAttribute.ErrorMessage, maxlen = minLengthAttribute.Length.ToString() });
            }
            #endregion

            #region reg
            RegularExpressionAttribute regularExpressionAttribute = propertyInfo.GetCustomAttribute<RegularExpressionAttribute>();
            if (regularExpressionAttribute != null && !Validates.ContainsKey("reg"))
            {
                Validates.Add("reg", new { message = regularExpressionAttribute.ErrorMessage, pattern = regularExpressionAttribute.Pattern });
            }
            #endregion

            return Validates;

        }

        #endregion
    }

}
